/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2002-2006 * Sleepycat Software. All rights reserved. * * $Id: Java5SharedLatchImpl.java,v 1.1 2006/05/06 09:00:34 ckaestne Exp $ */ package com.sleepycat.je.latch; import java.util.concurrent.locks.ReentrantReadWriteLock; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.dbi.EnvironmentImpl; /** * Java5SharedLatchImpl provides an implementation of the SharedLatch * interface. By using a wrapper class we can avoid link errors when we run in * Java 1.4 JVMs. LatchSupport will only reference this class if it knows that * the ReentrantReadWriteLock class is available at runtime through * Class.forName(). LatchSupport only references this class through the * SharedLatch interface and only constructs this using * * Class.forName("Java5LatchImpl").newInstance(); */ class Java5SharedLatchImpl extends ReentrantReadWriteLock implements SharedLatch { private String name; private boolean noteLatch; Java5SharedLatchImpl() { super(EnvironmentImpl.getFairLatches()); } /** * Set the latch name, used for latches in objects instantiated from the * log. */ public void setName(String name) { this.name = name; } /** * If noteLatch is true, then track latch usage in the latchTable. */ public void setNoteLatch(boolean noteLatch) { this.noteLatch = noteLatch; } /** * Acquire a latch for exclusive/write access. * * Wait for the latch if some other thread is holding it. If there are * threads waiting for access, they will be granted the latch on a FIFO * basis if fair latches are set. When the method returns, the latch is * held for exclusive access. * * @throws LatchException if the latch is already held by the current * thread for exclusive access. */ public void acquireExclusive() throws DatabaseException { try { if (isWriteLockedByCurrentThread()) { throw new LatchException(name + " already held"); } writeLock().lock(); assert (noteLatch ? noteLatch() : true);// intentional side effect; } finally { assert EnvironmentImpl.maybeForceYield(); } } public boolean acquireExclusiveNoWait() throws DatabaseException { try { if (isWriteLockedByCurrentThread()) { throw new LatchException(name + " already held"); } boolean ret = writeLock().tryLock(); assert (noteLatch ? noteLatch() : true);// intentional side effect; return ret; } finally { assert EnvironmentImpl.maybeForceYield(); } } /** * Acquire a latch for shared/read access. */ public void acquireShared() throws DatabaseException { try { readLock().lock(); assert (noteLatch ? noteLatch() : true);// intentional side effect } finally { assert EnvironmentImpl.maybeForceYield(); } } /** * Release an exclusive or shared latch. If there are other thread(s) * waiting for the latch, they are woken up and granted the latch. */ public void release() throws LatchNotHeldException { try { if (isWriteLockedByCurrentThread()) { writeLock().unlock(); return; } /* * There's no way to tell if a readlock is held by the current * thread so just try unlocking it. */ readLock().unlock(); } catch (IllegalMonitorStateException IMSE) { return; } finally { /* Intentional side effect. */ assert (noteLatch ? unNoteLatch() : true); } } /** * Only call under the assert system. This records latching by thread. */ private boolean noteLatch() throws LatchException { return LatchSupport.latchTable.noteLatch(this); } /** * Only call under the assert system. This records latching by thread. */ private boolean unNoteLatch() { return LatchSupport.latchTable.unNoteLatch(this, name); } }